﻿//
// KwData v2.0.0
// Copyright © 2009-2012 - Kasey Osborn (Kasewick@gmail.com)
// Ms-PL - Use and redistribute freely
//
// File:    BtreeKeysValues.cs
// Purpose: Defines generic API for Keys and Values properties.
//

using System;
using System.Collections.Generic;

namespace Kw.Data
{
    public partial class BtreeDictionary<TKey, TValue>
    {
        public partial class BtreeKeys :
            System.Collections.Generic.ICollection<TKey>,
            System.Collections.Generic.IEnumerable<TKey>,
            System.Collections.ICollection,
            System.Collections.IEnumerable
        {
            BtreeDictionary<TKey, TValue> tree;

            #region Constructors

            public BtreeKeys (BtreeDictionary<TKey, TValue> newTree)
            {
                this.tree = newTree;
            }

            #endregion

            #region Properties

            // Implements ICollection<TKey> and object ICollection.
            public int Count
            { get { return tree.Count; } }

            #endregion

            #region Methods

            public void CopyTo (TKey[] array, int index)
            {
                if (array == null)
                    throw new ArgumentNullException ("index", "Value cannot be null.");

                if (index < 0)
                    throw new ArgumentOutOfRangeException ("index", "Specified argument was out of the range of valid values.");

                if (index + Count > array.Length)
                    throw new ArgumentException ("Destination array is not long enough to copy all the items in the collection. Check array index and length.", "index");

                foreach (TKey key in this)
                {
                    array[index] = key;
                    ++index;
                }
            }

            #endregion

            #region Iteration

            public IEnumerator<TKey> GetEnumerator ()
            { return new BtreeKeysEnumerator (tree); }


            // Long form used for 5% performance increase.
            private class BtreeKeysEnumerator : IEnumerator<TKey>
            {
                BtreeDictionary<TKey, TValue> target;
                Leaf<TKey, TValue> currentLeaf;
                int leafIndex;

                public BtreeKeysEnumerator (BtreeDictionary<TKey, TValue> tree)
                {
                    target = tree;
                    Reset ();
                }

                object System.Collections.IEnumerator.Current
                { get { return (object) Current; } }

                public TKey Current
                { get { return currentLeaf.GetKey (leafIndex); } }

                public bool MoveNext ()
                {
                    if (++leafIndex < currentLeaf.KeyCount)
                        return true;

                    leafIndex = 0;
                    currentLeaf = currentLeaf.RightLeaf;
                    return currentLeaf != null;
                }

                public void Reset ()
                {
                    leafIndex = -1;
                    currentLeaf = target.FirstLeaf;
                }

                public void Dispose () { Dispose (true); GC.SuppressFinalize (this); }
                protected virtual void Dispose (bool disposing) { }
            }

            #endregion

            #region Explicit properties and methods

            void ICollection<TKey>.Add (TKey key)
            { throw new NotSupportedException (); }

            void ICollection<TKey>.Clear ()
            { throw new NotSupportedException (); }

            bool ICollection<TKey>.Contains (TKey key)
            { return tree.ContainsKey (key); }

            bool ICollection<TKey>.IsReadOnly
            { get { return true; } }

            bool ICollection<TKey>.Remove (TKey key)
            { throw new NotSupportedException (); }

            #endregion
        }



        public partial class BtreeValues :
            System.Collections.Generic.ICollection<TValue>,
            System.Collections.Generic.IEnumerable<TValue>,
            System.Collections.ICollection,
            System.Collections.IEnumerable
        {
            private BtreeDictionary<TKey, TValue> tree;

            #region Constructors

            public BtreeValues (BtreeDictionary<TKey, TValue> newTree)
            {
                this.tree = newTree;
            }

            #endregion

            #region Properties

            public int Count
            { get { return tree.Count; } }

            #endregion

            #region Methods

            public void CopyTo (TValue[] array, int index)
            {
                if (array == null)
                    throw new ArgumentNullException ("index", "Value cannot be null.");

                if (index < 0)
                    throw new ArgumentOutOfRangeException ("index", "Specified argument was out of the range of valid values.");

                if (index + Count > array.Length)
                    throw new ArgumentException ("Destination array is not long enough to copy all the items in the collection. Check array index and length.", "index");

                foreach (TValue value in this)
                {
                    array[index] = value;
                    ++index;
                }
            }

            #endregion

            #region Iteration

            public IEnumerator<TValue> GetEnumerator ()
            {
                for (Leaf<TKey, TValue> currentLeaf = tree.FirstLeaf; ; )
                {
                    for (int leafIndex = 0; leafIndex < currentLeaf.KeyCount; ++leafIndex)
                        yield return currentLeaf.GetValue (leafIndex);

                    currentLeaf = currentLeaf.RightLeaf;
                    if (currentLeaf == null)
                        break;
                }
            }

            #endregion

            #region Explicit properties and methods

            /// </exclude>
            void ICollection<TValue>.Add (TValue value)
            { throw new NotSupportedException (); }

            void ICollection<TValue>.Clear ()
            { throw new NotSupportedException (); }

            bool ICollection<TValue>.Contains (TValue value)
            { return tree.ContainsValue (value); }

            bool ICollection<TValue>.IsReadOnly
            { get { return true; } }

            bool ICollection<TValue>.Remove (TValue val)
            { throw new NotSupportedException (); }

            #endregion
        }

    }
}
